#include "StdAfx.h"
#include "cppcvt.h"
//#include <iostream>
//#include <locale.h>

const std::string scvt::ws2s(const std::wstring& ws)
{ 
	return WChar2Ansi(ws.c_str()); 
}

const std::wstring scvt::s2ws(const std::string& s)
{
	return Ansi2WChar(s.c_str(),s.size());
}

/*
const std::string scvt::ws2s(const std::wstring& ws)
{
	std::string curLocale = setlocale(LC_ALL, NULL);        // curLocale = "C";

	std::setlocale(LC_ALL, "chs"); 

	const wchar_t* _Source = ws.c_str();
	size_t _Dsize = 2 * ws.size() + 1;
	char *_Dest = new char[_Dsize];
	memset(_Dest,0,_Dsize);
	std::wcstombs(_Dest,_Source,_Dsize);
	string result = _Dest;
	delete []_Dest;

	std::setlocale(LC_ALL, curLocale.c_str());

	return result;
}


const std::wstring scvt::s2ws(const std::string& s)
{
	std::setlocale(LC_ALL, "chs"); 

	const char* _Source = s.c_str();
	size_t _Dsize = s.size() + 1;
	wchar_t *_Dest = new wchar_t[_Dsize];
	wmemset(_Dest, 0, _Dsize);
	std::mbstowcs(_Dest,_Source,_Dsize);
	wstring result = _Dest;
	delete []_Dest;

	std::setlocale(LC_ALL, "C");

	return result;
}
*/

/*
mbstate_t in_cvt_state;
mbstate_t out_cvt_state;

const std::wstring scvt::s2ws(const std::string& s)
{
	std::locale sys_loc("");

	const char* src_str = s.c_str();
	const size_t BUFFER_SIZE = s.size() + 1;

	wchar_t* intern_buffer = new wchar_t[BUFFER_SIZE];
	wmemset(intern_buffer, 0, BUFFER_SIZE);

	const char* extern_from = src_str;
	const char* extern_from_end = extern_from + s.size();
	const char* extern_from_next = 0;
	wchar_t* intern_to = intern_buffer;
	wchar_t* intern_to_end = intern_to + BUFFER_SIZE;
	wchar_t* intern_to_next = 0;

	typedef std::codecvt<wchar_t, char, mbstate_t> CodecvtFacet;

	CodecvtFacet::result cvt_rst =
		std::use_facet<CodecvtFacet>(sys_loc).in(
		in_cvt_state,
		extern_from, extern_from_end, extern_from_next,
		intern_to, intern_to_end, intern_to_next);
	if (cvt_rst != CodecvtFacet::ok) {
		switch(cvt_rst) {
case CodecvtFacet::partial:
	std::cerr << "partial";
	break;
case CodecvtFacet::error:
	std::cerr << "error";
	break;
case CodecvtFacet::noconv:
	std::cerr << "noconv";
	break;
default:
	std::cerr << "unknown";
		}
		std::cerr    << ", please check in_cvt_state."
			<< std::endl;
	}
	std::wstring result = intern_buffer;

	delete []intern_buffer;

	return result;
}

const std::string scvt::ws2s(const std::wstring& ws)
{
	std::locale sys_loc("");

	const wchar_t* src_wstr = ws.c_str();
	const size_t MAX_UNICODE_BYTES = 4;
	const size_t BUFFER_SIZE =
		ws.size() * MAX_UNICODE_BYTES + 1;

	char* extern_buffer = new char[BUFFER_SIZE];
	memset(extern_buffer, 0, BUFFER_SIZE);

	const wchar_t* intern_from = src_wstr;
	const wchar_t* intern_from_end = intern_from + ws.size();
	const wchar_t* intern_from_next = 0;
	char* extern_to = extern_buffer;
	char* extern_to_end = extern_to + BUFFER_SIZE;
	char* extern_to_next = 0;

	typedef std::codecvt<wchar_t, char, mbstate_t> CodecvtFacet;

	CodecvtFacet::result cvt_rst =
		std::use_facet<CodecvtFacet>(sys_loc).out(
		out_cvt_state,
		intern_from, intern_from_end, intern_from_next,
		extern_to, extern_to_end, extern_to_next);
	if (cvt_rst != CodecvtFacet::ok) {
		switch(cvt_rst) {
case CodecvtFacet::partial:
	std::cerr << "partial";
	break;
case CodecvtFacet::error:
	std::cerr << "error";
	break;
case CodecvtFacet::noconv:
	std::cerr << "noconv";
	break;
default:
	std::cerr << "unknown";
		}
		std::cerr    << ", please check out_cvt_state."
			<< std::endl;
	}
	std::string result = extern_buffer;

	delete []extern_buffer;

	return result;
}
*/

std::string WChar2Ansi(LPCWSTR pwszSrc)
{
	int nLen = WideCharToMultiByte(CP_ACP, 0, pwszSrc, -1, NULL, 0, NULL, NULL);

	if (nLen<= 0) return std::string("");

	char* pszDst = new char[nLen];
	if (NULL == pszDst) return std::string("");

	WideCharToMultiByte(CP_ACP, 0, pwszSrc, -1, pszDst, nLen, NULL, NULL);
	pszDst[nLen -1] = 0;

	std::string strTemp(pszDst);
	delete [] pszDst;

	return strTemp;
}

std::wstring Ansi2WChar(LPCSTR pszSrc, int nLen)
{
	int nSize = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pszSrc, nLen, 0, 0);
	if(nSize <= 0) return NULL;

	WCHAR *pwszDst = new WCHAR[nSize+1];
	if( NULL == pwszDst) return NULL;

	MultiByteToWideChar(CP_ACP, 0,(LPCSTR)pszSrc, nLen, pwszDst, nSize);
	pwszDst[nSize] = 0;

	if( pwszDst[0] == 0xFEFF)                    // skip Oxfeff
		for(int i = 0; i < nSize; i ++) 
			pwszDst[i] = pwszDst[i+1]; 

	std::wstring wcharString(pwszDst);
	delete pwszDst;

	return wcharString;
}

